﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using 历史记录.DataAccessLayer;
using 历史记录.Helper;

namespace 历史记录.BusinessLogicLayer
{
    /// <summary>
    /// 单表存储
    /// </summary>
    public class SingleBll<T> : DisposableBase, IBLL<T>
        where T : Model, new()
    {
        public const string Table = "data";

        /// <summary>
        /// 数据库对象
        /// </summary>
        public IDAL<T> DAL { get; }

        /// <summary>
        /// 最早记录时间
        /// </summary>
        public DateTime Start { get; private set; }

        /// <summary>
        /// 最晚记录时间
        /// </summary>
        public DateTime End { get; private set; }

        /// <summary>
        /// 删除间隔
        /// </summary>
        public TimeSpan DeleteSpan { get; }

        /// <summary>
        /// 保存天数默认保存五天
        /// </summary>
        public TimeSpan SaveSpan { get; }

        internal SingleBll(IDAL<T> dal, TimeSpan span, TimeSpan delete)
        {
            DAL = dal;
            SaveSpan = span;
            DeleteSpan = delete;
            if (!DAL.GetTableList().Contains(Table))
            {
                DAL.InitTables(Table);
            }
            else
            {
                Start = DAL.Min(Table);
                End = DAL.Max(Table);
            }
        }

        /// <summary>
        /// 插入数据
        /// </summary>
        /// <param name="insertObjs"></param>
        /// <returns></returns>
        public bool Insertable(List<T> insertObjs)
        {
            End = DateTime.Now;
            if (insertObjs == null) return false;
            return DAL.Insertable(Table, insertObjs);
        }

        /// <summary>
        /// 查询数据
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="start">开始时间</param>
        /// <param name="end">结束时间</param>
        /// <param name="Select">一个应用于每个源元素的转换函数</param>
        /// <param name="Where">查询条件</param>
        /// <returns></returns>
        public IEnumerable<IEnumerable<TResult>> Queryable<TResult>(DateTime start, DateTime end, Expression<Func<T, TResult>> Select, Expression<Func<T, bool>> Where = null) where TResult : new()
        {
            Expression<Func<T, bool>> think = a => a.Id >= start && a.Id <= end;
            yield return DAL.Queryable(Table, Select, think.AndAlso(Where));
        }

        /// <summary>
        /// 查询数据
        /// </summary>
        /// <param name="start">开始时间</param>
        /// <param name="end">结束时间</param>
        /// <param name="Where">查询条件</param>
        /// <returns></returns>
        public IEnumerable<IEnumerable<T>> Queryable(DateTime start, DateTime end, Expression<Func<T, bool>> Where = null)
        {
            Expression<Func<T, bool>> think = a => a.Id >= start && a.Id <= end;
            yield return DAL.Queryable(Table, think.AndAlso(Where));
        }

        /// <summary>
        /// 判断是否需要更新
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="date">判断时间</param>
        /// <param name="data">插入数据</param>
        /// <returns></returns>
        public bool UpDate(DateTime date, List<T> data)
        {
            var span = date - Start;
            if (span > DeleteSpan && span > SaveSpan)
            {
                var start = date - SaveSpan;
                DAL.DeleteMany(Table, a => a.Id < start);
                Start = start;
            }
            return false;
        }

        protected override void OnDispose()
        {
            DAL.Dispose();
        }
    }
}